package com.etl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.etl.constants.CommonConstant;
import com.etl.lock.RedisLock;
import com.etl.service.IEtlBatchSchedulerService;
import com.etl.util.CodeGeneratedUtil;
import com.etl.util.DateUtil;
import com.etl.entity.EtlTaskBatch;
import com.etl.entity.EtlBusinessBatch;
import com.etl.mapper.EtlTaskBatchMapper;
import com.etl.mapper.EtlBusinessBatchMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author ：poplar
 * @date ：Created in 2020/4/26 3:26 下午
 * @description：自动化抽取各步骤接口实现类
 * @modified By：
 * @version: 1.0$
 */
@Slf4j
@Service
public class EtlBatchSchedulerServiceImpl implements IEtlBatchSchedulerService {

    @Resource
    EtlTaskBatchMapper batchTaskMapper;
    @Resource
    private RedisLock redisLock;
    @Resource
    private EtlBusinessBatchMapper etlBusinessBatchMapper;

    // 定时任务前缀
    private final static String TOKEN_PREFIX = CommonConstant.CACHE_PREFIX + ".EtlBatchScheduler:%s";

    /**
     * 获取redis key
     * @param key
     * @return
     */
    private String schedulerKey(String key) {
        return String.format(TOKEN_PREFIX, key);
    }


    /**
     * 根据在批次表中配置的定时抽取类型，生成任务表
     */
    @Override
    public void creatTask() {

        log.info("【定时任务】- 【创建任务】操作时间为：" + new Date());

        QueryWrapper<EtlBusinessBatch> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", 1);
        queryWrapper.orderByAsc("batch");
        List<EtlBusinessBatch> etlBusinessBatches = etlBusinessBatchMapper.selectList(queryWrapper);

        for (EtlBusinessBatch etlBusinessBatch : etlBusinessBatches) {
            EtlTaskBatch etlTaskBatch = new EtlTaskBatch();
            etlTaskBatch.setCreateTime(new Date());
            etlTaskBatch.setBatch(etlBusinessBatch.getBatch());
            switch (etlBusinessBatch.getTaskType()) {
                case 0 : {
                    // 固定时间
                    String taskVal = etlBusinessBatch.getTaskVal();
                    if (Strings.isNotBlank(taskVal)) {
                        etlTaskBatch.setTaskId(CodeGeneratedUtil.genUUID());
                        Date parses = DateUtil.parses((DateUtil.getCurrentDate() + " " + taskVal), "yyyy-MM-dd HH:mm:ss");
                        etlTaskBatch.setWaitRunTime(parses);
                        batchTaskMapper.insert(etlTaskBatch);
                    }
                    break;
                }
                case 1 : {
                    // 按 小时 间隔
                    String taskVal = etlBusinessBatch.getTaskVal();
                    if (Strings.isNotBlank(taskVal)) {
                        int count = 24 / Integer.parseInt(taskVal);
                        for (int i = 1; i <= count; i++) {
                            etlTaskBatch.setTaskId(CodeGeneratedUtil.genUUID());
                            int house = i * Integer.parseInt(taskVal);
                            String s = String.valueOf(house);
                            if (house < 24) {
                                String time = s + ":00:00";
                                Date parses = DateUtil.parses((DateUtil.getCurrentDate() + " " + time), "yyyy-MM-dd HH:mm:ss");
                                etlTaskBatch.setWaitRunTime(parses);
                                batchTaskMapper.insert(etlTaskBatch);
                            }
                        }
                    }
                    break;
                }
                case 2 : {
                    // 按分间隔
                    String taskVal = etlBusinessBatch.getTaskVal();
                    if (Strings.isNotBlank(taskVal)) {
                        int count = 24 * 60 / Integer.parseInt(taskVal);
                        for (int i = 1; i <= count; i++) {
                            etlTaskBatch.setTaskId(CodeGeneratedUtil.genUUID());
                            int minute = i * Integer.parseInt(taskVal);
                            int house = minute / 60;        // 小时
                            minute = minute % 60;           // 分

                            String s = String.valueOf(house);
                            String s1 = String.valueOf(minute);

                            if (house == 24 && minute == 0) {
                                continue;
                            }

                            if (house == 24) {
                                s = "00";
                            }

                            if (minute == 0) {
                                s1 = "00";
                            }

                            String time = s + ":" + s1 + ":00";
                            Date parses = DateUtil.parses((DateUtil.getCurrentDate() + " " + time), "yyyy-MM-dd HH:mm:ss");
                            etlTaskBatch.setWaitRunTime(parses);
                            batchTaskMapper.insert(etlTaskBatch);
                        }
                    }
                    break;
                }
                default: {
                    break;
                }
            }
        }
    }


    @Override
    public EtlTaskBatch getTask() {

        Date currentDate = new Date();
        // 取出所有小于当前时间的任务
        QueryWrapper<EtlTaskBatch> batchTaskQueryWrapper = new QueryWrapper<>();
        batchTaskQueryWrapper.le("wait_run_time", currentDate).orderByAsc("wait_run_time");
        List<EtlTaskBatch> etlTaskBatches = batchTaskMapper.selectList(batchTaskQueryWrapper);
        if (etlTaskBatches == null || etlTaskBatches.size() == 0) {
            //当前没有待执行的任务,返回
            return null;
        }

        // 取和当前时间最近的一条任务，判断执行时间是否在 5 秒之内
        EtlTaskBatch etlTaskBatch = etlTaskBatches.get(etlTaskBatches.size() - 1);
        Long aLong = DateUtil.timeBetween(etlTaskBatch.getWaitRunTime(), currentDate);
        if (aLong <= 5000) {
            log.info("【定时任务】:{}-取出当前待执行任务【{}批次】",DateUtil.getCurrent(), etlTaskBatch.getBatch());
            return etlTaskBatch;
        }
        etlTaskBatch = etlTaskBatches.get(0);
        log.info("【定时任务】:{}-未获取到当前待执行任务，开始从堆积任务中获取【{}批次】",DateUtil.getCurrent(), etlTaskBatch.getBatch());
        // 取时间最小的任务开始执行
        return etlTaskBatch;
    }

    @Override
    public int deleteTask(EtlTaskBatch batchTask) {
        if (batchTask == null || Strings.isBlank(batchTask.getTaskId())) {
            return -1;
        }
        int i = batchTaskMapper.deleteById(batchTask.getTaskId());
        log.info("【定时任务】- 【删除】操作时间为：" + new Date() + " 任务为：" + batchTask + "，结果：" + i);
        return i;
    }

    @Override
    public boolean lockBatchTask(String lockValue) {
        String batchScheduler = schedulerKey("batchScheduler");
        boolean lock = redisLock.lock(batchScheduler, lockValue);
        log.info("【定时任务】：{}-lock 值为：{}",DateUtil.getCurrent(),lockValue);
        return lock;
    }

    @Override
    public void unlockBatchTask(String lockValue) {
        String batchScheduler = schedulerKey("batchScheduler");
        log.info("【定时任务】：{} -释放锁",DateUtil.getCurrent());
        redisLock.unlock(batchScheduler, lockValue);
    }
}
